#ifndef __REFEREE_H
#define __REFEREE_H

#include "main.h"
#include <stdbool.h>
#include "dr16.hpp"


#define REFEREE_LEN_HEADER 5  //帧头长度
#define REFEREE_LEN_CMDID  2  // cmd_id长度
#define REFEREE_LEN_TAIL   2  //帧尾长度

#define REFEREE_FRAME_HEADER 0xA5  //数据帧起始字节，固定值为 0xA5

/* 帧头偏移量 */
#define REFEREE_OFFSET_SOF         0  //帧头SOF偏移量
#define REFEREE_OFFSET_DATA_LENGTH 1  //帧头数据长度偏移量
#define REFEREE_OFFSET_SEQ         3  //帧头包序号偏移量
#define REFEREE_OFFSET_CRC8        4  //帧头CRC8偏移量

/* 帧内有效数据包偏移量 */
#define REFEREE_OFFSET_DATA (REFEREE_LEN_HEADER + REFEREE_LEN_CMDID)

/* com_id 命令码 ID */
#define ID_GAME_STATUS              0x0001  //比赛状态
#define ID_GAME_RESULT              0X0002  //比赛结果
#define ID_GAME_ROBOT_HP            0X0003  //机器人血量数据
#define ID_GAME_FIELD_EVENT         0x0101  //场地事件数据
#define ID_REFEREE_WARNING          0x0104  //裁判警告信息
#define ID_DART_REMAIN_TIME         0x0105  //飞镖发射口倒计时
#define ID_GAME_ROBOT_STATUS        0x0201  //机器人性能体系
#define ID_POWER_HEAT_DATA          0x0202  //实时底盘缓冲能量和射击热量
#define ID_GAME_ROBOT_POS           0x0203  //机器人位置
#define ID_BUFF                     0x0204  //机器人增益和底盘能量
#define ID_ROBOT_HURT               0x0206  //伤害状态
#define ID_SHOOT_DATA               0x0207  //实时射击信息
#define ID_REMAIN_BULLET            0x0208  //允许发弹量
#define ID_RFID_STATUS              0x0209  //机器人 RFID 状态
#define ID_GRUAND_ROBOT_POSITION	  0x020B  //地面机器人位置
#define ID_ROBOT_INTERACTION        0x0301	//机器人到裁判系统
/* 图传链路 */
#define ID_CUSTOM_ROBOT             0x0302  //自定义控制器
#define ID_KEYBOARD                 0x0304	//键鼠数据
#define ID_ROBOT_CUSTOM             0x0309  //机器人回传自定义控制器
/* 比赛状态数据： 0x0001。发送频率： 1Hz */
typedef __PACKED_STRUCT {
	uint8_t  game_type : 4;      //比赛类型
	uint8_t  game_progress : 4;  //当前比赛阶段
	uint16_t stage_remain_time;
	uint64_t SyncTimeStamp;
}
ext_game_status_t;

/* 比赛结果数据： 0x0002。发送频率：比赛结束后发送 */
typedef __PACKED_STRUCT {
	uint8_t winner;  // 0 平局 1 红方胜利 2 蓝方胜利
}
ext_game_result_t;

/* 机器人血量数据： 0x0003。发送频率： 1Hz */
typedef __PACKED_STRUCT {
	uint16_t red_1_robot_HP;
	uint16_t red_2_robot_HP;
	uint16_t red_3_robot_HP;
	uint16_t red_4_robot_HP;
	uint16_t reserved;         //保留
	uint16_t red_7_robot_HP;  //红方哨兵血量
	uint16_t red_outpost_HP;  //红方前哨站血量
	uint16_t red_base_HP;     //红方基地血量
	uint16_t blue_1_robot_HP;
	uint16_t blue_2_robot_HP;
	uint16_t blue_3_robot_HP;
	uint16_t blue_4_robot_HP;
	uint16_t blue_5_robot_HP;
	uint16_t blue_7_robot_HP;
	uint16_t blue_outpost_HP;
	uint16_t blue_base_HP;
}ext_game_robot_HP_t;

/* clang-format off */
/* 场地事件数据： 0x0101。发送频率： 1Hz 周期发送 */
typedef __PACKED_STRUCT {
	uint32_t event_type;
} ext_event_data_t;
/* clang-format on */

/* 裁判警告信息： cmd_id (0x0104)。发送频率：警告发生后发送 */
typedef __PACKED_STRUCT {
	uint8_t level; 				//警告等级
	uint8_t offending_robot_id; //犯规机器人 ID
	uint8_t count;				//犯规机器人违规次数
}
ext_referee_warning_t;

/* clang-format off */
/* 飞镖发射口倒计时：cmd_id (0x0105)。发送频率：1Hz周期发送，发送范围：己方机器人 */
typedef __PACKED_STRUCT {
	uint8_t dart_remaining_time;
	uint16_t  dart_info;
} ext_dart_remaining_time_t;
/* clang-format on */

/* 哨兵自主决策指令：0x0120 机器人间通信： 0x0301 */
typedef __PACKED_STRUCT {
    uint32_t sentry_cmd; //详见裁判系统串口协议
} ext_sentry_cmd_t;

/* 雷达自主决策指令：0x0121 机器人间通信： 0x0301 */
typedef __PACKED_STRUCT {
    uint8_t radar_cmd; //详见裁判系统串口协议
} ext_radar_cmd_t;

/* 比赛机器人状态： 0x0201。发送频率： 10Hz */
typedef __PACKED_STRUCT {	
	uint8_t robot_id; 								//本机器人 ID
	uint8_t robot_level; 							//机器人等级
	uint16_t current_HP; 							//机器人当前血量
	uint16_t maximum_HP; 							//机器人上限血量
	uint16_t shooter_barrel_cooling_value; 			//机器人射击热量每秒冷却值
	uint16_t shooter_barrel_heat_limit; 			//机器人射击热量上限
	uint16_t chassis_power_limit; 					//机器人底盘功率上限
	uint8_t power_management_gimbal_output : 1;    //gimbal 口输出，0 为无输出，1 为 24V 输出
	uint8_t power_management_chassis_output : 1;   //chassis 口输出，0 为无输出，1 为 24V 输出
	uint8_t power_management_shooter_output : 1;   //shooter 口输出，0 为无输出，1 为 24V 输出
}
ext_game_robot_status_t;

/* 实时功率热量数据： 0x0202。 发送频率： 50Hz */
typedef __PACKED_STRUCT {
	uint16_t reserved0;
	uint16_t reserved1;
	float    reserved2;
	volatile uint16_t buffer_energy;  //底盘功率缓冲 单位 J 焦耳
	uint16_t          shooter_id1_17mm_cooling_heat;  // 1 号 17mm 枪口热量
	uint16_t          shooter_id2_17mm_cooling_heat;  // 2 号 17mm 枪口热量
	uint16_t          shooter_id1_42mm_cooling_heat;  // 42mm 枪口热量
}
ext_power_heat_data_t;

/* 机器人位置： 0x0203。发送频率： 10Hz */
typedef __PACKED_STRUCT {
    float x;  //本机器人位置 x 坐标，单位 m，下同
    float y;
    float angle;  //本机器人测速模块的朝向，单位：度。正北为 0 度
}
ext_game_robot_pos_t;

/* clang-format off */
/* 机器人增益： 0x0204。发送频率： 1Hz 周期发送 */
typedef __PACKED_STRUCT {
	uint8_t recovery_buff;			//机器人回血增益（百分比，值为 10 表示每秒恢复血量上限的 10%）
	uint8_t cooling_buff;			//机器人射击热量冷却倍率（直接值，值为 5 表示 5 倍冷却）
	uint8_t defence_buff;			//机器人防御增益（百分比，值为 50 表示 50%防御增益）
	uint8_t vulnerability_buff;		//机器人负防御增益（百分比，值为 30 表示-30%防御增益）
	uint16_t attack_buff;			//机器人攻击增益（百分比，值为 50 表示 50%攻击增益）
	uint8_t remaining_energy;		//bit 0：在剩余能量≥50%时为 1，其余情况为 0		bit 1：在剩余能量≥30%时为 1，其余情况为 0
									//bit 2：在剩余能量≥15%时为 1，其余情况为 0		bit 3：在剩余能量≥5%时为 1，其余情况为 0		
									//bit4：在剩余能量≥1%时为 1，其余情况为 0
} ext_buff_t;
/* clang-format on */

/* 伤害状态： 0x0206。发送频率：伤害发生后发送 */
typedef __PACKED_STRUCT {
    uint8_t armor_id : 4;   /* 当血量变化类型为装甲伤害，
                            代表装甲 ID，其中数值为 0-3 号代表机器人的四个装甲片，
                            其他血量变化类型，该变量数值为 0 */
    uint8_t HP_deduction_reason : 4;  //血量变化类型
}
ext_robot_hurt_t;

/* 实时射击信息： 0x0207。发送频率：射击后发送 */
typedef __PACKED_STRUCT {
    uint8_t bullet_type;   			//子弹类型: 1： 17mm 弹丸 2： 42mm 弹丸
    uint8_t shooter_number;    		//发射机构 ID
    uint8_t launching_frequency;   	//弹丸射速（单位：Hz）
    float   initial_speed;  		//弹丸初速度（单位：m/s）
}
ext_shoot_data_t;

/* 子弹剩余发射数： 0x0208。发送频率： 10Hz 周期发送， 所有机器人发送 */
typedef __PACKED_STRUCT {
    uint16_t projectile_allowance_17mm;  /* 17mm 子弹剩余发射数目,
                                         联盟赛: 全队步兵与英雄剩余可发射 17mm 弹丸总量 */
    uint16_t projectile_allowance_42mm;  // 42mm 子弹剩余发射数目
    uint16_t remaining_gold_coin;        // 剩余金币数量
}
ext_bullet_remaining_t;

/* clang-format off */
/* 机器人 RFID 状态： 0x0209。发送频率： 1Hz */
typedef __PACKED_STRUCT {
    uint32_t rfid_status;
} ext_rfid_status_t;
/* bit 0：己方基地增益点 
 bit 1：己方中央高地增益点 
 bit 2：对方中央高地增益点 
 bit 3：己方梯形高地增益点 
 bit 4：对方梯形高地增益点 
 bit 5：己方地形跨越增益点（飞坡）（靠近己方一侧飞坡前） 
 bit 6：己方地形跨越增益点（飞坡）（靠近己方一侧飞坡后） 
 bit 7：对方地形跨越增益点（飞坡）（靠近对方一侧飞坡前） 
 bit 8：对方地形跨越增益点（飞坡）（靠近对方一侧飞坡后） 
 bit 9：己方地形跨越增益点（中央高地下方） 
 bit 10：己方地形跨越增益点（中央高地上方） 
 bit 11：对方地形跨越增益点（中央高地下方） 
 bit 12：对方地形跨越增益点（中央高地上方） 
 bit 13：己方地形跨越增益点（公路下方）
 bit 14：己方地形跨越增益点（公路上方） 
 bit 15：对方地形跨越增益点（公路下方） 
 bit 16：对方地形跨越增益点（公路上方） 
 bit 17：己方堡垒增益点 
 bit 18：己方前哨站增益点 
 bit 19：己方与兑换区不重叠的补给区/RMUL 补给区 
 bit 20：己方与兑换区重叠的补给区 
 bit 21：己方大资源岛增益点 
 bit 22：对方大资源岛增益点 
 bit 23：中心增益点（仅 RMUL 适用） 
 bit 24-31：保留*/
/* clang-format on */
/* 飞镖选手端指令数据： 0x020A。发送频率： 3Hz */
typedef __PACKED_STRUCT {
    uint8_t dart_launch_opening_status;  // 1：关闭 2：正开启/关闭中  0：已开启 
		uint8_t reserved;  
		uint16_t target_change_time;  			 //切换击打目标时的比赛剩余时间，单位：秒
		uint16_t latest_launch_cmd_time;		 //最后一次操作手确定发射指令时比赛剩余时间
} ext_dart_client_cmd_t;

/*地面机器人位置： 0x020B  发送频率： 1Hz*/
typedef __PACKED_STRUCT { 
	float hero_x; 
	float hero_y; 
	float engineer_x; 
	float engineer_y; 
	float standard_3_x; 
	float standard_3_y; 
	float standard_4_x; 
	float standard_4_y; 
	float reserved; 
	float reserved1; 
}ext_ground_robot_position_t;
/* 雷达标记进度数据： 0x020C。发送频率： 1Hz */
typedef __PACKED_STRUCT {
		uint8_t mark_hero_progress;  					//对方机器人易伤：100时发送1,否则0。 详见裁判系统附录
} ext_radar_mark_data_t;

/* 哨兵自主决策信息同步： 0x020D。发送频率： 1Hz */
typedef __PACKED_STRUCT {
    uint32_t sentry_info;;	//详见裁判系统附录
		uint16_t sentry_info_2;
} ext_sentry_info_t;

/* 雷达自主决策信息同步： 0x020E。发送频率： 1Hz */
typedef __PACKED_STRUCT {
    uint8_t radar_info; ;	//详见裁判系统附录
} ext_radar_info_t;

/*********** 机器人间交互数据 **********/
/* 交互数据接收信息： 0x0301 */
typedef __PACKED_STRUCT {
    uint16_t data_cmd_id;  //数据段的内容 ID
    uint16_t sender_ID;
    uint16_t receiver_ID;
}
ext_student_interactive_header_data_t;

/* 学生机器人间通信 cmd_id 0x0301， 内容 ID:0x0200~0x02FF */
typedef __PACKED_STRUCT {
    uint8_t data[128];  //此处大小可修改
}
robot_interactive_data_t;

/* 客户端删除图形 机器人间通信： 0x0301 */
typedef __PACKED_STRUCT {
    uint8_t operate_tpye;
    uint8_t layer;
}
ext_client_custom_graphic_delete_t;

/* 图形数据 */
typedef __PACKED_STRUCT {
    uint8_t  graphic_name[3];
    uint32_t operate_tpye : 3;
    uint32_t graphic_tpye : 3;
    uint32_t layer : 4;
    uint32_t color : 4;
    uint32_t start_angle : 9;
    uint32_t end_angle : 9;
    uint32_t width : 10;
    uint32_t start_x : 11;
    uint32_t start_y : 11;
    uint32_t radius : 10;
    uint32_t end_x : 11;
    uint32_t end_y : 11;
}
graphic_data_struct_t;

/* clang-format off */
/* 客户端绘制一个图形 机器人间通信： 0x0301 */
typedef __PACKED_STRUCT {
    graphic_data_struct_t grapic_data_struct;
} ext_client_custom_graphic_single_t;

/* 客户端绘制二个图形 机器人间通信： 0x0301 */
typedef __PACKED_STRUCT {
    graphic_data_struct_t grapic_data_struct[2];
} ext_client_custom_graphic_double_t;

/* 客户端绘制五个图形 机器人间通信： 0x0301 */
typedef __PACKED_STRUCT {
    graphic_data_struct_t grapic_data_struct[5];
} ext_client_custom_graphic_five_t;

/* 客户端绘制七个图形 机器人间通信： 0x0301 */
typedef __PACKED_STRUCT {
    graphic_data_struct_t grapic_data_struct[7];
} ext_client_custom_graphic_seven_t;
/* clang-format on */

/* 客户端绘制字符 机器人间通信： 0x0301 */
typedef __PACKED_STRUCT {
    graphic_data_struct_t grapic_data_struct;
    uint8_t               data[30];
}
ext_client_custom_character_t;

/* 发送数据结构体 */
typedef struct {
    uint16_t                              cmd_id;
    ext_student_interactive_header_data_t data_header;
    uint8_t                               data[112];
    uint16_t                              frame_tail;
} referee_send_data_t;

typedef enum {
    EmptyOperation = 0, /* 空操作 */
    AddGraphic,          /* 增加图形 */
    ModifyGraphic,       /* 修改图形 */
    DeleteGrapic        /* 删除图形 */
} GrapicOperation;

/* 图传链路 */
/* 自定义控制器向机器人： 0x0302 */
typedef __PACKED_STRUCT {
		uint8_t                               data[30];
} ext_custom_robot_data_t;

/* 图传链路键鼠信息： 0x0304 */
typedef __PACKED_STRUCT { 
		int16_t  	mouse_x; 
		int16_t  	mouse_y; 
		int16_t  	mouse_z; 
		int8_t   	left_button; 
		int8_t 	 	right_button; 
		uint16_t 	keyboard_value; 
		uint16_t 	reserved; 
} ext_vt_data_t; 

/* 机器人向自定义控制器： 0x0309 */
typedef __PACKED_STRUCT {
    uint16_t                              cmd_id;
		uint8_t                               data[30];
    uint16_t                              frame_tail; 
} ext_robot_custom_data_t;
/* 外部声明裁判系统接收数据 */
extern ext_game_status_t              game_status;               //比赛状态
extern ext_game_result_t              game_result;               //比赛结果
extern ext_game_robot_HP_t            game_robot_HP;             //机器人血量数据
extern ext_event_data_t               game_field_event;          //场地事件数据
extern ext_referee_warning_t          judge_warning;             //裁判警告信息
extern ext_game_robot_status_t        game_robot_status;         //比赛机器人状态
extern ext_power_heat_data_t          power_heat_data;           //实时功率热量数据
extern ext_game_robot_pos_t           game_robot_pos;            //机器人位置
extern ext_buff_t                     robot_buff;                //机器人增益
extern ext_robot_hurt_t               robot_hurt;                //伤害状态
extern ext_shoot_data_t               shoot_data;                //实时射击信息
extern ext_rfid_status_t              rfid_status;               //机器人 RFID 状态
extern ext_bullet_remaining_t         bullet_remaining;          //子弹剩余发射数
extern ext_ground_robot_position_t	  ground_robot_position;     //地面机器人位置

extern ext_custom_robot_data_t				custom_robot;
extern ext_vt_data_t           				vt_data;

/* 裁判系统接收缓冲区大小 */
#define REFEREE_RECV_BUF_SIZE 255

extern uint8_t RefereeRecvBuf[REFEREE_RECV_BUF_SIZE];
extern uint8_t VTRecvBuf[REFEREE_RECV_BUF_SIZE];

bool Referee_Decode(uint8_t *RefereeRecvBuf);
int  Referee_ConfigFrameData(uint16_t cmd_id, void *data, int length);
void referee_init(void);
#define COOLING_HEAT_MAX 265

void referee_debug(void);

class VT_Link {
   public:
    VT_Link(void);
	 
		void reset(void);
    bool VT_Decode(uint8_t *VTRecvBuf);
	  void tcp_trans_init(void);
		void update(void);
		void debug(void);
		__PC get_pc(void);

    bool is_button_pressing(uint8_t button);
    bool is_button_pressed_down(uint8_t button);

    bool is_key_pressed_down(uint16_t key);
    bool is_key_clicked(uint16_t key);
    bool is_key_pressing(uint16_t key);

   private:
		__PC		vt_;
};  //图传链路

extern VT_Link 		vt;

#endif  //__REFEREE_H
